using UnityEngine;

namespace VoxelEngine
{
	public class Block
	{
		public const byte MinLight = 51;

		public const byte MaxLight = byte.MaxValue;

		public bool visited;

		private bool modelSpawned;

		public const int NumberedBlocksStart = 128;

		public const int NumberedBlocksEnd = 143;

		public const int ColorBlocksStart = 144;

		public const int ColorBlocksEnd = 160;

		private Chunk _chunk;

		public readonly short _wx;

		public readonly short _wy;

		public readonly short _wz;

		public byte _byteType;

		private byte _light;

		public Chunk Chunk
		{
			get
			{
				return _chunk;
			}
			set
			{
				_chunk = value;
			}
		}

		public BlockType Type
		{
			get
			{
				return (BlockType)_byteType;
			}
			set
			{
				_byteType = (byte)value;
				if (_chunk != null && _chunk.WorldRef != null)
				{
					_chunk.WorldRef.UpdateBlockInWorldBytes(this);
				}
			}
		}

		public byte Light
		{
			get
			{
				return _light;
			}
			set
			{
				byte b = (byte)Mathf.Clamp(value, 51, 255);
				if (_light != b)
				{
					_light = b;
					if (_chunk != null)
					{
						_chunk.SetDirty();
						_chunk.WorldRef.UpdateBlockInWorldBytes(this);
					}
				}
			}
		}

		public Block(BlockType type, int wx = 0, int wy = 0, int wz = 0)
		{
			_wx = (short)wx;
			_wy = (short)wy;
			_wz = (short)wz;
			_byteType = (byte)type;
			if (Type == BlockType.Height || Type == BlockType.WorldBound)
			{
				_light = byte.MaxValue;
			}
			else
			{
				_light = 51;
			}
		}

		public void UpdateNeighbourBlocks()
		{
			for (int i = _wx - 1; i <= _wx + 1; i++)
			{
				for (int j = _wy - 1; j <= _wy + 1; j++)
				{
					for (int k = _wz - 1; k <= _wz + 1; k++)
					{
						if (_chunk != null)
						{
							Block block = _chunk.WorldRef[i, j, k];
							if (block.Chunk != null)
							{
								block.Chunk.SetDirty();
							}
						}
					}
				}
			}
		}

		public bool IsTranslucent()
		{
			BlockType type = Type;
			if (type == BlockType.Water || type == BlockType.Glass)
			{
				return true;
			}
			return false;
		}

		public bool IsAsteriskTranslucent()
		{
			return IsAsteriskTranslucentBlock(Type);
		}

		public static bool IsAsteriskTranslucentBlock(BlockType blockType)
		{
			switch (blockType)
			{
			case BlockType.Foliage:
			case BlockType.LightGreenFoliage:
			case BlockType.BlueFoliage:
			case BlockType.RedFoliage:
				return true;
			default:
				return false;
			}
		}

		public static bool IsHalfBlock(BlockType blockType)
		{
			switch (blockType)
			{
			case BlockType.HalfTopBrick:
			case BlockType.HalfBottomBrick:
			case BlockType.HalfTopGrayBrick:
			case BlockType.HalfBottomGrayBrick:
				return true;
			default:
				return false;
			}
		}

		public bool IsSolid()
		{
			switch (Type)
			{
			case BlockType.Water:
			case BlockType.Air:
			case BlockType.Height:
			case BlockType.WorldBound:
				return false;
			default:
				return true;
			}
		}

		public bool Indestructible()
		{
			BlockType type = Type;
			if (type == BlockType.HardStone || type == BlockType.Lava)
			{
				return true;
			}
			return false;
		}

		public BlockVolume Volume()
		{
			switch (Type)
			{
			case BlockType.HalfBottomBrick:
			case BlockType.HalfBottomGrayBrick:
				return BlockVolume.HalfBottom;
			case BlockType.HalfTopBrick:
			case BlockType.HalfTopGrayBrick:
				return BlockVolume.HalfTop;
			default:
				return BlockVolume.Full;
			}
		}

		public bool IsCutout()
		{
			switch (Type)
			{
			case BlockType.Foliage:
			case BlockType.LightGreenFoliage:
			case BlockType.BlueFoliage:
			case BlockType.RedFoliage:
			case BlockType.Glass:
			case BlockType.Bush:
				return true;
			default:
				return false;
			}
		}

		public bool IsCollapsedBlock()
		{
			switch (Type)
			{
			case BlockType.Foliage:
			case BlockType.LightGreenFoliage:
			case BlockType.BlueFoliage:
			case BlockType.RedFoliage:
				return true;
			default:
				return false;
			}
		}

		public bool IsCutoutCollisionBlock()
		{
			BlockType type = Type;
			if (type == BlockType.Glass || type == BlockType.Bush)
			{
				return true;
			}
			return false;
		}

		public Vector2 TextureBottomUV()
		{
			return BlockTypes.Instance.GetBlockType(_byteType).TextureBottomUV();
		}

		public Vector2 TextureTopUV()
		{
			return BlockTypes.Instance.GetBlockType(_byteType).TextureTopUV();
		}

		public Vector2 TextureSideUV()
		{
			return BlockTypes.Instance.GetBlockType(_byteType).TextureSideUV();
		}

		public Vector2 TextureUV()
		{
			return BlockTypes.Instance.GetBlockType(_byteType).TextureUV();
		}

		public bool Destroy(byte light = 51)
		{
			return BlockTypes.Instance.GetBlockType(_byteType).Destroy(this, (_chunk == null) ? null : _chunk.WorldRef.WorldTransform, light);
		}

		public bool Create(BlockType type)
		{
			return BlockTypes.Instance.GetBlockType(_byteType).Create(this, type, (_chunk == null) ? null : _chunk.WorldRef.WorldTransform);
		}

		public bool Is3DModel()
		{
			return BlockTypes.Instance.GetBlockType(_byteType).Model() != null;
		}

		public ParticleSystem DestroyParticle()
		{
			return BlockTypes.Instance.GetBlockType(_byteType).DestroyParticle();
		}

		public GameObject Model()
		{
			return BlockTypes.Instance.GetBlockType(_byteType).Model();
		}

		public void Spawn3DModelIfNeeded()
		{
			if (!modelSpawned)
			{
				modelSpawned = BlockTypes.Instance.GetBlockType(_byteType).Spawn3DModelIfNeeded(this);
			}
		}
	}
}
